<?php

namespace App\Http\Controllers\Admin;

use App\Enums\ResponseEnum;
use App\Models\Logs\LoginLog;
use App\Http\Controllers\AdminController;
use App\Models\Sanctum\PersonalAccessToken;
use App\Models\System\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Jenssegers\Agent\Agent;

class AuthController extends AdminController
{
    private int $expTime = 7*1440;
    private string $deviceName;

    public function login(Request $request)
    {
        $request->validate([
            'username' => 'required',
            'password' => 'required',
        ]);
        $this->deviceName = $request->get('device_name', 'admin-sanctum');
        return $this->attempt([
            'username' => base64_decode($request->get('username')),
            'password' => base64_decode($request->get('password')),
        ]);
    }

    public function logout(Request $request)
    {
        $user = $request->user();
        $this->recordLog('退出登录', $user);
        $user->currentAccessToken()->delete();
        PersonalAccessToken::clearUserToken($request);
        return $this->succeed();
    }

    private function attempt(array $credentials)
    {
        $user = User::query()->where($this->accountField($credentials['username']), $credentials['username'])->where('status', 1)
            ->first(['id', 'avatar', 'username', 'mobile', 'email', 'display_name', 'password', 'sex', 'describe']);
        if (!$user || !Hash::check($credentials['password'], $user->password)) {
            return $this->error(ResponseEnum::USER_SERVICE_LOGIN_ERROR);
        }
        $token = $this->getToken($user);
        $this->recordLog('登录成功', $user);
        return $this->respondWithToken($token, $user);
    }

    private function getToken($user)
    {
        if (config('custom.isSSO')) {
            $user->tokens()->delete();
        }
        $permissions = $user->getAllPermissions()->pluck('name')->toArray();
        return $user->createToken($this->deviceName, $permissions, now()->addMinutes($this->expTime))->plainTextToken;
    }

    private function respondWithToken(string $token, $user): \Illuminate\Http\JsonResponse
    {
        return $this->succeed([
            'type' => 'Bearer',
            'token' => $token,
            'expires_in' => $this->expTime * 60,
            'userInfo' => [
                'avatar' => $user->avatar,
                'userName' => $user->username,
                'mobile' => $user->mobile,
                'email' => $user->email,
                'displayName' => $user->display_name,
                'sex' => $user->sex,
                'describe' => $user->describe,
                'loginTime' => date('Y-m-d H:i:s')
            ]
        ]);
    }

    private function accountField(string $account): string
    {
        $field = 'username';
        if (filter_var($account, FILTER_VALIDATE_EMAIL)) {
            $field = 'email';
        } elseif (preg_match('/^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/', $account)) {
            $field = 'mobile';
        }
        return $field;
    }

    private function recordLog(string $message, $user): void
    {
        try {
            $agent = new Agent();
            $ipData = $this->libClientIp()->get();
            $user->update([
                'last_login_ip' => $ipData['ip'],
                'last_login_time' => now()
            ]);
            LoginLog::query()->create([
                'user_id' => $user->id,
                'username' => $user->username,
                'message' => $message,
                'platform' => $agent->platform(),
                'browser' => $agent->browser(),
                'ip' => $ipData['ip'],
                'ip_address' => $ipData["region"],
                'user_agent' => $agent->getUserAgent(),
            ]);
        }catch (\Exception $e) {
            report($e);
        }
    }
}
